﻿#pragma once
//HTTP常⻅Header
//• Content - Type: 数据类型(text / html等)
//• Content - Length : Body的⻓度
//• Host : 客⼾端告知服务器, 所请求的资源是在哪个主机的哪个端⼝上;
//• User - Agent: 声明⽤⼾的操作系统和浏览器版本信息;
//• Referer : 当前⻚⾯是从哪个⻚⾯跳转过来的;
//• Location : 搭配3xx状态码使⽤, 告诉客⼾端接下来要去哪⾥访问;
//• Cookie : 在客⼾端存储少量信息.通常⽤于实现会话(session)的功能;
//• connection：
//
//-------------------------------- -
//Content - Type对照表引入到unodered_map中，构造函数中完成即可，我们只需显式的插入几个常用的即可；只需要注意当我们的k为unkonw的事后，v为text / html，所以当我们代码中找_path的后缀没找到，就让后缀为.unkonw，这样kv映射就是text / html
//
//-------------------------------- -
//频繁的bind同一个端口号 会出错的原因：
//和TCP的四次挥手有关，导致端口号仍然在被使用，服务器无法再次bind端口号，所以binderror，今天重点不在于问题如何产生，而是问题如何解决
//
//我们需要在封装套接字的文件中的基类新增一个接口，设置套接字地址复用
//SetSocketAddrReuse(); 在内部调用setsockopt接口。setsockopt意为设置套接字属性：
//
//int setsockopt(int sockfd, int level, int optname,
//    const void* optval, socklen_t optlen);
//参数：套接字，哪一层，选项名字，选项值，选项长度
//
//void SetSockgetAddrReuse() override
//{
//    int opt = 1;
//    ::setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
//}
//
//SetSockgetAddrReuse()在创建套接字之后立即使用
//
//设置套接字地址复用是必要的操作，避免服务器挂掉了，影响到了之前的所有已连接的链接，没有地址复用，只能进行更换端口号，服务器当然不能随意更改端口号，比如双11下的tb更换端口号，影响巨大
//-------------------------------- -
//• Host : 客⼾端告知服务器, 所请求的资源是在哪个主机的哪个端⼝上;
//如：Host: 8.137.19.140 : 8888
//
//Q：服务端不就是主机吗？为什么还需要主机IP字段？
//A：有可能我们接收到我们请求的服务器并不是最终服务器，而是一个中间服务器，也叫作代理服务器，代理服务器接收到字后，通过Host字段得知是向最终服务器发送的请求，代理服务器会自己充当客户端向最终服务器发送请求，然后接收到响应，再以服务器的身份向客户端返回响应
//
//-------------------------------- -
//• Referer : 当前⻚⾯是从哪个⻚⾯跳转过来的;
//Referer:http://8.137.19.140:8888/2.html
//
//比如a标记的跳转功能，当你从首页跳转到另一个页面的时候，此时请求信页面的报文中的请求报头中的Referer:就会记录你是从首页跳过来的，
//
//意义：网站的回退？禁止某一个网页地址的访问(不做响应)，等......
//
//
//-------------------------------- -
//• Location : 搭配3xx状态码使⽤, 告诉客⼾端接下来要去哪⾥访问;
//后面说
//
//-------------------------------- -
//• Cookie : 在客⼾端存储少量信息.通常⽤于实现会话(session)的功能;
//加餐课说，下面会简略地用代码体现一下
//
//-------------------------------- -
//•connection(长链接)：⽤于控制和管理客⼾端与服务器之间的连接状态
//Connection : keep - alive：表⽰希望保持连接以复⽤TCP连接
//Connection : close ：表⽰请求 / 响应完成后，应该关闭TCP连接
//
//比如一个网站中的资源很多，图片音频都不止一个，所以我们每次获取资源都需要发送请求，而发送请求的本质就是TCP客户端发送连接，所以会造成众多的TCP的connect的连接请求，这不好；所以Connection 字段可以⽤于管理持久连接（也称为⻓连接）。持久连接允许客⼾端和服务器在请求 / 响应完成后不⽴即关闭TCP连接，以便在同⼀个连接上发送多个请求和接收多个响应。(一个TCP连接处理多个请求的高效场景)
//
//注：在HTTP / 1.1协议中是默认长连接的，在HTTP / 1.0中不是
//
//我们之前的计算器就是1.1版本，模拟的长连接，我们的请求是堆积的，我们不断的读取请求，不断的做出回应
//
//而我们今天的代码是1.0版本，不是长连接，因为我们的服务端代码中的HandlerSock接口中，读取到了请求后，处理后返回应答后，就立马关闭了sockfd；
//
//而长连接读取请求的时候，就要处理粘报的问题，计算机中是通过len字段，而http中自带 Content - Length字段
//
//
//-------------------------------- -
//其余字段的说明 在wps中有
//Accept：客⼾端可接受的响应内容类型
//Accept - Encoding：客⼾端⽀持的数据压缩格式
//Accept - Language：客⼾端可接受的语⾔类型
//
//Accept - Encoding：我们代码无法体现，在浏览器中的图片过大或者视频过大就会事先进行压缩
//
//-------------------------------- -
//浏览器是会对资源做缓存的，这就是为什么第一次访问网页速度慢，后面就快了，这个是浏览器的策略
//
//-------------------------------- -
//状态码的理解：
//
//各种非正常状况都要清晰的反映给客户端，让客户端知道错误原因
//
//3xx：看一半让你充会员 或者让你登录 类似的操作
//4xx：比如404的错误 叫作客户端错误 不要以为是服务端没有资源的错误，因为这是不合理的请求 ，错在客户端，你跟你爸要1个亿 谁错？
//5xx：服务端错误，内部文件打开错误，线程或进程创建错误等，这种才叫服务器错误
//
//注：大多数的5xx错误，一般会以4xx的错误展现，防止黑客测试服务端的错误所在，全都是4xx，无法测试，不让外人知道服务端错误的触发场景
//
//Q：HTTP协议规定的状态码，还能不按要求返回吗？
//A：是的，各家浏览器公司互相竞争，谁也不想让自己的服务端错误场景被测试出来，而且就算是错误返回2xx也是可以的，因为这只是让客户端看到的罢了
//
//301：Moved Permanently：⽹站换域名后，⾃动跳转到新域名；搜索引擎更新⽹站链接时使⽤(又叫作永久重定向)
//
//不管是301还是302 307都会让应答里面具有一个location字段，该字段保留的是新的地址，302和307的差别就是请求方法的差别，我们不用管
//
//301是永久的重定向，类似于更新书签
//
//更新书签：其实就是浏览器引擎更新自己的库里的链接罢了，所以3xx这种状态码都是给搜索引擎看的
//
//现在的dy的抖加，其实在搜索引擎中就是叫做sop。其会让浏览器搜索任何东西的时候，都会增加到搜索到你的网站的概率，利用搜索引擎的算法，其实最经典的就是标题党
//
//所以依旧是维护一张状态描述表即可，也是在httpserver的构造函数中进行硬编码的插入该表
//
//现在我们在代码中 直接将状态码设置为3xx  然后把location字段设置为qq.com或者我们自己的web目录下的文件 都可以，现在只要访问我们的服务器，不管你访问什么 都会返回location字段所代表的资源